所有基于C编写的app的入口都是main函数,但iOS应用程序有点不同。不同就是你不需要为iOS应用程序而自己编写main函数,当你使用Xcode创建工程的时候就已经提供了。除非一些特殊情况,否则你不应该修改Xcode提供的main函数实现,在下图中我们可以看到Xcode为我们生成了一个main.m文件:
UIApplicationMain
截图中默认的iOS程序就是从main函数开始执行的,但是在main函数中我们其实只能看到一个方法,这个方法内部是一个消息循环(相当于一个死循 环),因此运行到
|
|
UIApplicationMain这个方法之后程序不会自动退出,而只有当用户手动关闭程序这个循环才结束。这个方法有四个参数:
- 第一个参数和第二个参数其实就是main函数的参数,分别代表:参数个数、参数内容;
- 第三个参数代表UIApplication类(或子类)字符串,这个参数默认为nil则代表默认为UIApplication类,用户 可以自定义一个类继承于这个类;如果为nil则等价于NSStringFromClass([UIApplication class]),大家可以自己试验,效果完全一样;UIApplication是单例模式,一个应用程序只有一个UIApplication对象或子对 象;
- 第四个参数是UIApplication的代理类字符串,默认生成的是AppDelegate类,这个类主要用于监听整个应用程序生命 周期的各个事件,当UIApplication运行过程中引发了某个事件之后会调用代理中对应的方法;
|
|
main
函数的两个参数(int argc, char *argv[])
,iOS中没有用到,包括这两个参数是为了与标准ANSI C保持一致。
UIApplicationMain
函数,前两个参数和main
函数一样,重点是后两个,官方说明是这样的:
// If nil is specified for principalClassName, the value for NSPrincipalClass from the Info.plist is used. If there is no
// NSPrincipalClass key specified, the UIApplication class is used. The delegate class will be instantiated using init.
UIKIT_EXTERN int UIApplicationMain(int argc, char argv[], NSString principalClassName, NSString *delegateClassName);
后两个参数分别表示程序的主要类(principal class)和代理类(delegate class)。如果主要类为nil,将从Info.plist中获取,如果Info.plist中不存在对应的key,则默认为UIApplication;如果代理类为nil,将在新建工程时创建。
根据UIApplicationMain函数,程序将进入AppDelegate.m,这个文件是Xcode新建工程时自动生成的。
上面实例代码中有一个很重要的函数UIApplicationMain,它主要是创建app的几个核心对象来处理以下过程:
- 从可用
Storyboard
文件加载用户界面 - 调用
AppDelegate
自定义代码来做一些初始化设置 - 将app放入
Main Run Loop
环境中来响应和处理与用户交互产生的事件
Swift中的Main函数
用OC语言创建的项目,一定会有一个main.m文件,里面有一个main函数,在这个函数中唤醒app。如果在app启动时放置断点,可以看到应用程序调用栈,main函数作为程序启动后的第二个函数被调用,然后在main函数中再启动UIApplication,并绑定AppDelegate。如下图:
但是Swift项目中没有一个名为main.swift的文件,为什么app的入口没有了?官方文档的说法是这样的:
In Xcode, Mac templates default to including a “main.swift” file, but for iOS apps the default for new iOS project templates is to add @UIApplicationMain to a regular Swift file. This causes the compiler to synthesize a mainentry point for your iOS app, and eliminates the need for a “main.swift” file.
这段话的意思是,Swift项目中添加了@UIApplicationMain 到swift文件中,使得编译器合成了一个app入口,所以不需要main.swift文件。
可能苹果认为我们并不需要自行配置app入口,所以干脆简化了项目配置,使用更加简单的方式启动应用,但有时候我们可能需要自己配置入口,例如我们要创建一个UIApplication的子类时。
自定义UIApplicationMain
如果你希望通过自行配置入口的方式来创建一个UIApplication子类,首先定义一个UIApplication的子类:
|
|
然后新建main.swift文件:
|
|
在Appdelegate的最顶部声明@UIApplicationMain,表示该类是application的delegate。
如果不用该属性标识,另外一种做法是在main.swift中调用UIApplicationMain函数,设置delegate和application。以上我们就是根据这种方法来设置的。
去掉Appdelegate的@UIApplicationMain,我们就将main.swift设置为了入口。
UIApplicationMain的参数
以前OC的main函数的argv参数是一个字符串指针,打印出来后是应用程序的路径。
Swift中main函数的 Process.unsafeArgv 参数变成了一串十六进制数字,应该也是代表应用程序地址。